import React, { useEffect, useMemo, useRef, useState } from 'react';
import type { Employee as Emp, MessageParams, PageEmp } from '@/type/employeeType';
import { Card, Col, Row, Input, Tree, message, Button, Table, Avatar, Pagination, Spin, Modal, Form, Select, DatePicker, Tag, Cascader, Checkbox, Drawer } from 'antd';
import { fetchDepartmentsList } from '@/store/modules/departmentStore';
import { useDispatch, useSelector } from 'react-redux';
import { deleteEmployee, fetchEmployee, addEmployee, findEmployee, updateEmployee, assignEmployeeRole, sendMessage } from '@/store/modules/employeeStore';
import { ExclamationCircleFilled, SearchOutlined, UserOutlined } from '@ant-design/icons';
import Upload from '@/components/Upload/Upload';
import lodash from 'lodash';
import './Employee.scss';
import dayjs from 'dayjs';
import type { GetProp } from 'antd';
import { useAppSelector, useAppDispatch } from '@/hooks';
import { fetchEnabledRoleList } from '@/store/modules/roleStore';


const Employee: React.FunctionComponent = () => {
  const dispatch = useDispatch();
  const appDispatch = useAppDispatch();
  const employeeList = useAppSelector(state => state.employeeStore.employees);
  // const departments = useAppSelector(state => state.departmentStore.departments);
  const total = useAppSelector(state => state.employeeStore.total);
  const departments = useSelector((state: any) => state.departmentStore.departments);
  // const employeeList = useSelector((state: any) => state.employeeStore.employees);
  // const total = useSelector((state: any) => state.employeeStore.total);
  const [page, setPage] = useState<PageEmp>({ page: 1, pagesize: 10, keyword: '', departmentId: -1 });
  const [loading, setLoading] = useState<boolean>(false);
  const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
  const [edit, setEdit] = useState<boolean>(false);
  const title = useMemo(() => edit ? '编辑员工' : '添加员工', [edit]);
  const mapFormOfEmployment = useRef([{ value: 1, label: '正式工' }, { value: 0, label: '非正式' }]);
  const [form] = Form.useForm();
  const [isModalRole, setIsModalRole] = useState<boolean>(false);
  const [chkecboxOptions, setChkecboxOptions] = useState<{ label: string, value: number }[]>([]);
  const [selecteEmployee, setSelecteEmployee] = useState<Emp[]>([]);
  const [open, setOpen] = useState<boolean>(false);
  const [formData, setFormData] = useState<Emp>({
    formOfEmployment: -1,
    mobile: '',
    staffPhoto: '',
    correctionTime: '',
    timeOfEntry: '',
    username: '',
    workNumber: '',
    departmentId: -1,
    roleIds: [],
  });
  const messageType = useRef([{ value: 1, label: '通知消息' }, { value: 2, label: '提示消息' }, { value: 3, label: '重要消息' }, { value: 4, label: '紧急消息' },]);
  const [selectionType, setSelectionType] = useState<'checkbox' | 'radio'>('checkbox');
  const [messageForm] = Form.useForm();
  const columns = [
    { title: '头像', render: (_: Emp, record: Emp) => <Avatar src={record.staffPhoto} icon={<UserOutlined />}></Avatar> },
    { title: '姓名', dataIndex: 'username', key: 'username' },
    { title: '手机号', dataIndex: 'mobile', key: 'mobile' },
    { title: '工号', dataIndex: 'workNumber', key: 'workNumber' },
    { title: '聘用形式', render: (_: Emp, record: Emp) => <span>{record.formOfEmployment === 0 ? '临时' : '正式'}</span> },
    { title: '部门', dataIndex: 'departmentName', key: 'departmentName' },
    { title: '入职时间', dataIndex: 'timeOfEntry', key: 'timeOfEntry' },
    {
      title: '操作', render: (_: Emp, record: Emp) => {
        return (
          <>
            <Button type="primary" onClick={() => handleEditEmployee(record)}>编辑</Button>
            <Button type="primary" onClick={() => handleAssignRole(record)}>角色</Button>
            <Button type="primary" danger onClick={() => handleDeleteEmployee(record)}>删除</Button>
          </>
        );
      },
    },
  ];

  /**
   * @description 获取部门列表的回调函数
   * */
  const fetchDepartments = async () => {
    try {
      setLoading(true);
      await dispatch(fetchDepartmentsList()).unwrap();
    } catch (rejectedValueOrSerializedError: any) {
      message.error(rejectedValueOrSerializedError);
    } finally {
      setLoading(false);
    }
  };

  /**
   * @description 获取员工列表的回调函数
   * */
  const fetchEmployeeList = async (page: PageEmp) => {
    try {
      setLoading(true);
      await dispatch(fetchEmployee(page)).unwrap();
    } catch (rejectedValueOrSerializedError: any) {
      message.error(rejectedValueOrSerializedError);
    } finally {
      setLoading(false);
    }
  };

  /**
   * @description 分页器发生变化的回调函数
   * */
  const changePagination = async (_page: number, pagesize: number) => {
    const newPage: PageEmp = { ...page, page: _page, pagesize };
    setPage(newPage);
    await fetchEmployeeList(newPage);
  };

  /**
   * @description 点击删除按钮的回调函数
   * */
  const handleDeleteEmployee = async (record: Emp) => {
    Modal.confirm({
      title: '温馨提示',
      icon: <ExclamationCircleFilled />,
      content: `确认删除${record.username}吗?`,
      okText: '确定',
      cancelText: '取消',
      onOk: async (): Promise<void> => {
        try {
          const deleteMessage = await dispatch(deleteEmployee(record.id)).unwrap();
          await fetchEmployeeList(page);
          message.success(deleteMessage);
        } catch (rejectedValueOrSerializedError: any) {
          message.error(rejectedValueOrSerializedError);
        }
      },
    });
  };


  const selectTree = (key: any, event: any) => {
    const newPage: PageEmp = { ...page, departmentId: event.node.id, page: 1 };
    setPage(newPage);
    fetchEmployeeList(newPage);
  };

  const changeKeyword = lodash.throttle((event: any) => {
    const newPage: PageEmp = { ...page, keyword: event.target.value, page: 1 };
    setPage(newPage);
    fetchEmployeeList(newPage);
  }, 2000);


  const handleOk = async () => {
    if (edit) {
      try {
        const { username, workNumber, mobile, formOfEmployment, departmentId, correctionTime, timeOfEntry } = form.getFieldsValue();
        const newForm = { username, workNumber, mobile, formOfEmployment, departmentId, correctionTime: `${correctionTime.$y}-${correctionTime.$M + 1}-${correctionTime.$D}`, timeOfEntry: `${timeOfEntry.$y}-${timeOfEntry.$M + 1}-${timeOfEntry.$D}` };
        const newFormData = { ...formData, ...newForm };
        setFormData(newFormData);
        const updateMessage = await appDispatch(updateEmployee(newFormData)).unwrap();
        await fetchEmployeeList(page);
        setIsModalOpen(false);
        message.success(updateMessage);
      } catch (rejectedValueOrSerializedError: any) {
        message.error(rejectedValueOrSerializedError);
      }
    } else {
      try {
        const { username, workNumber, mobile, formOfEmployment, departmentId, correctionTime, timeOfEntry } = form.getFieldsValue();
        const newForm = { username, workNumber, mobile, formOfEmployment, departmentId: departmentId[departmentId.length - 1], correctionTime: `${correctionTime.$y}-${correctionTime.$M + 1}-${correctionTime.$D}`, timeOfEntry: `${timeOfEntry.$y}-${timeOfEntry.$M + 1}-${timeOfEntry.$D}` };
        const newFormData = { ...formData, ...newForm };
        const addMessage = await appDispatch(addEmployee(newFormData)).unwrap();
        await fetchEmployeeList(page);
        setIsModalOpen(false);
        message.success(addMessage);
      } catch (rejectedValueOrSerializedError: any) {
        message.error(rejectedValueOrSerializedError);
      }
    }
  };

  const handleCancel = () => {
    setIsModalOpen(false);
  };

  const handleAddEmployee = () => {
    setIsModalOpen(true);
    setEdit(false);
  };

  const handleEditEmployee = async (record: Emp) => {
    try {
      setIsModalOpen(true);
      const employeeDetail = await appDispatch(findEmployee(record.id as number)).unwrap();
      setEdit(true);
      setFormData(employeeDetail);
      form.setFieldsValue({ ...employeeDetail, timeOfEntry: dayjs(employeeDetail.timeOfEntry), correctionTime: dayjs(employeeDetail.correctionTime) });
    } catch (rejectedValueOrSerializedError: any) {
      message.error(rejectedValueOrSerializedError);
    }
  };

  const uploadStaffPhoto = (staffPhoto: string) => {
    setFormData({ ...formData, staffPhoto });
  };

  const afterOpenChange = () => {
    form.resetFields();
  };

  const handleAssignRole = async (record: Emp) => {
    try {
      const employeeDetail = await appDispatch(findEmployee(record.id as number)).unwrap();
      const enabledRoleList = await appDispatch(fetchEnabledRoleList()).unwrap();
      const chkecboxOptions = enabledRoleList.map(item => ({ label: item.name, value: item.id }));
      setIsModalRole(true);
      setChkecboxOptions(chkecboxOptions);
      setFormData(employeeDetail);
    } catch (rejectedValueOrSerializedError: any) {
      message.error(rejectedValueOrSerializedError);
    }
  };

  const handleAssignSuccess = async () => {
    try {
      const data = ({ id: formData.id, roleIds: formData.roleIds as number[] }) as { id: number, roleIds: number[] };
      const asignMessage = await appDispatch(assignEmployeeRole(data)).unwrap();
      setIsModalRole(false);
      message.success(asignMessage);
    } catch (rejectedValueOrSerializedError: any) {
      message.error(rejectedValueOrSerializedError);
    }
  };

  const handleassignCancel = () => {
    setIsModalRole(false);
  };


  const changeCheckbox: GetProp<typeof Checkbox.Group, 'onChange'> = (checkedValues) => {
    setFormData({
      ...formData,
      roleIds: ([...checkedValues]) as number[],
    });
  };

  const onChange = (selectedRowKeys: React.Key[], selectedRows: Emp[]) => {
    setSelecteEmployee(selectedRows);
  };


  const sendNotification = () => {
    if (!selecteEmployee.length) return message.warning('请选择需要群发的员工');
    setOpen(true);
  };


  const closeDrawer = () => {
    setOpen(false);
  };


  const send = async () => {
    try {
      const { type, content } = messageForm.getFieldsValue();
      const messageParams: MessageParams = { type, content, userIds: (selecteEmployee.map(item => item.id)) as number[] };
      const messageTip = await appDispatch(sendMessage(messageParams)).unwrap();
      setOpen(false);
      message.success(messageTip);
    } catch (rejectedValueOrSerializedError: any) {
      message.error(rejectedValueOrSerializedError);
    }
  };
  const renderTable = () => {
    if (loading) {
      return (
        <div className="loading">
          <Spin spinning={loading}>加载中</Spin>
        </div>
      );
    } else {
      return (
        <Col span={19}>
          <Row>
            <Col span={24}>
              <Row>
                <Col span={17}>
                  <Button type="primary" onClick={sendNotification}>群发通知</Button>
                </Col>
                <Col span={7}>
                  <Button type="primary" onClick={handleAddEmployee}>添加员工</Button>
                  <Button type="primary">excel导入</Button>
                  <Button type="primary">excel导出</Button>
                </Col>
              </Row>
            </Col>
          </Row>
          <Table rowSelection={{ type: selectionType, onChange }} rowKey="id" columns={columns} dataSource={employeeList} pagination={false} bordered></Table>
          <Pagination showSizeChanger defaultCurrent={page.page} total={total} onChange={changePagination} />
        </Col>
      );
    }
  };

  useEffect(() => {
    Promise.all([fetchDepartments(), fetchEmployeeList(page)]);
  }, []);

  return (
    <div className="employee layui-anim layui-anim-scale">
      <Card>
        <Row>
          <Col span={5}>
            <Input addonBefore={<SearchOutlined />} placeholder="请输入员工姓名进行搜索" value={page.keyword} onChange={changeKeyword}></Input>
            {departments[0] && <Tree onSelect={selectTree} style={{ width: '100%' }} treeData={departments} defaultExpandAll={true} fieldNames={{ title: 'name', key: 'id', children: 'children' }} showLine></Tree>}
          </Col>
          {renderTable()}
        </Row>
      </Card>
      <Modal width={700} title={title} open={isModalOpen} onOk={handleOk} onCancel={handleCancel} afterOpenChange={afterOpenChange}>
        <Form form={form}>
          <Form.Item label="员工姓名" name="username">
            <Input placeholder="请输入员工姓名"></Input>
          </Form.Item>
          <Form.Item label="员工工号" name="workNumber">
            <Input placeholder="请输入员工工号"></Input>
          </Form.Item>
          <Form.Item label="员工手机" name="mobile">
            <Input placeholder="请输入员工手机"></Input>
          </Form.Item>
          <Form.Item label="所属部门" name="departmentId">
            <Cascader searchValue={formData.departmentName} showSearch options={departments} fieldNames={{ label: 'name', value: 'id', children: 'children' }} placeholder="请选择所属部门" />
          </Form.Item>
          <Form.Item label="聘用形式" name="formOfEmployment">
            <Select placeholder="请选择聘用形式" options={mapFormOfEmployment.current}></Select>
          </Form.Item>
          <Form.Item label="入职时间" name="timeOfEntry">
            <DatePicker></DatePicker>
          </Form.Item>
          <Form.Item label="转正时间" name="correctionTime">
            <DatePicker></DatePicker>
          </Form.Item>
          <Form.Item label="员工头像">
            <Upload staffPhoto={formData.staffPhoto} uploadStaffPhoto={uploadStaffPhoto}></Upload>
          </Form.Item>
        </Form>
      </Modal>
      <Modal width={700} title="员工分配角色" open={isModalRole} onOk={handleAssignSuccess} onCancel={handleassignCancel} afterOpenChange={afterOpenChange}>
        <Checkbox.Group options={chkecboxOptions} value={formData.roleIds} onChange={changeCheckbox} />
      </Modal>

      <Drawer width={600} title="群发通知" onClose={closeDrawer} open={open}>
        <div className="employee-list">{selecteEmployee.map((item, index) => (<Tag color="#f50">@{item.username}</Tag>))}</div>
        <Form form={messageForm}>
          <Form.Item name="type">
            <Select placeholder="请选择消息等级" options={messageType.current}></Select>
          </Form.Item>
          <Form.Item name="content">
            <Input.TextArea placeholder="请输入消息内容" rows={4} maxLength={6}></Input.TextArea>
          </Form.Item>
          <Form.Item>
            <Button type="primary" htmlType="submit" onClick={send}>发送</Button>
          </Form.Item>
        </Form>
      </Drawer>

    </div>
  );
};

export default Employee;
